/*!
 * @file
 * @brief 日志控制相关方法
 *
 * Copyright (c) 2020 rxi
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the MIT license. See `log.c` for details.
 */

#pragma once

/*-----------------------------------------------------------------------------
 * HEADER FILES
 *---------------------------------------------------------------------------*/
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <time.h>

#ifdef _cplusplus
extern "C" {
#endif

/*-----------------------------------------------------------------------------
 * DATA STRUCTURE
 *---------------------------------------------------------------------------*/
/**
 * @brief 日志事件配置
 */
typedef struct gmi_log_event_st
{
    va_list ap;          ///< ??
    const char* format;  ///< 输出格式
    const char* file;    ///< 日志文件名
    struct tm* time;     ///< 本地时间
    void* udata;         ///< 输出数据
    int line;            ///< 文件行数
    int level;           ///< 日志等级
} GMI_LOG_EVENT;

typedef void (*log_outFn)(GMI_LOG_EVENT* ev);
typedef void (*log_LockFn)(bool lock, void* udata);

enum gmi_log_level_e
{
    GMI_LOG_TRACE,  // 追踪
    GMI_LOG_DEBUG,  // 调试
    GMI_LOG_INFO,   // 信息
    GMI_LOG_WARN,   // 警告
    GMI_LOG_ERROR,  // 错误
    GMI_LOG_FATAL   // 宕机
};

/*-----------------------------------------------------------------------------
 * HEADER FILES
 *---------------------------------------------------------------------------*/
#define gmi_log_trace(...) \
    gmi_log_out(GMI_LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__)
#define gmi_log_debug(...) \
    gmi_log_out(GMI_LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
#define gmi_log_info(...) \
    gmi_log_out(GMI_LOG_INFO, __FILE__, __LINE__, __VA_ARGS__)
#define gmi_log_warn(...) \
    gmi_log_out(GMI_LOG_WARN, __FILE__, __LINE__, __VA_ARGS__)
#define gmi_log_error(...) \
    gmi_log_out(GMI_LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__)
#define gmi_log_fatal(...) \
    gmi_log_out(GMI_LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__)

/*-----------------------------------------------------------------------------
 * FUNCTIONS DECLARATION
 *---------------------------------------------------------------------------*/

/**
 * @brief 将整形等级数值转换成字符串
 *
 * @param level
 * @return const char*
 */
const char* gmi_log_level_string(int level);

/**
 * @brief 锁定输出
 *
 * @param fn
 * @param udata
 */
void gmi_log_set_lock(log_LockFn fn, void* udata);

/**
 * @brief 设置最低日志等级
 *
 * @param level
 */
void gmi_log_set_level(int level);

/**
 * @brief 设置日志输出为安静模式
 * @note 在最低等级以下的日志将不会输出
 *
 * @param enable
 */
void gmi_log_set_quiet(bool enable);

/**
 * @brief 日志回调
 *
 * @param fn
 * @param udata
 * @param level
 * @return int
 */
int gmi_log_add_callback(log_outFn fn, void* udata, int level);

/**
 * @brief 添加日志存放输出功能
 *
 * @param fp
 * @param level
 * @return int
 */
int gmi_log_add_fp(FILE* fp, int level);

/**
 * @brief 日志输出
 *
 * @param level
 * @param file
 * @param line
 * @param format
 * @param ...
 */
void gmi_log_out(int level,
                 const char* file,
                 int line,
                 const char* format,
                 ...);

#ifdef _cplusplus
}
#endif
